﻿#pragma once

_NAMESPACE_BEGIN

typedef unsigned char __byte;

class Buffer
{
public:
	Buffer(const Buffer& cfrom)
	{
		Buffer& f=const_cast<Buffer&>(cfrom);//强制去掉const属性，为了将cfrom的candelete改为false

		b=f.b;
		capacity=f.capacity;
		size=f.size;
		pos=0;//转换所有权后指针指向头部
		candelete=f.candelete;
		f.candelete=false;			
	}
	Buffer(DWORD capacity=0);
	~Buffer();
	template<typename T>
	void in(const __byte* ptr,T len)
	{
		if((DWORD)len+size>capacity)
		{
			SetCapacity((DWORD)len+size);			
		}
		memcpy(b+size,ptr,(DWORD)len);
		size+=(DWORD)len;
	}
	template<typename T>
	void in(T t)
	{
		in((__byte*)&t,sizeof(t));
	}
	void in(CONST_REF(tstring)s)
	{
		in((__byte*)s.c_str(),(s.length()+1)*sizeof(TCHAR));
	}
	void in(CONST_REF(string)s)
	{
		in((__byte*)s.c_str(),s.length()+1);
	}
	template <typename T>
	void out(T& t)
	{
		t=*(T*)(b+pos);
		pos+=sizeof(T);
	}
	void out(tstring &s)
	{
		s=(TCHAR*)out();
		pos+=(s.size()+1)*sizeof(TCHAR);
	}
	void out(string &s)
	{
		s=(char*)out();
		pos+=s.size()+1;
	}
	void out( __byte *bf,int len)
	{
		memcpy(bf,(b+pos),len);
		pos+=len;
	}
	__byte* out()
	{
		return b+pos;
	}
	__byte* GetBuffer(){return b;}
	void SetBuffer(__byte* p,DWORD len);
	DWORD GetSize()const{return size;}
	void SetSize(DWORD s){this->size=s;if(s>this->capacity) SetCapacity(s);}
	DWORD GetCapacity(){return capacity;}
	void SetCapacity(DWORD c);
	DWORD GetPos(){return pos;}
	void SetPos(DWORD s){pos=s;}
	template<typename T>
	void operator +=(T len)
	{
		pos+=(DWORD)len;
	}
	//将缓冲所有权转移到另一个buffer
	void CopyTo(Buffer& to)
	{
		to.b=b;
		to.capacity=capacity;
		to.size=size;
		//to.pos=pos;//转换所有权后指针指向头部
		to.candelete=candelete;
		candelete=false;			
	}
	void Clear();

	template<typename T>
	friend Buffer& operator <<(Buffer& buffer,CONST_REF(T) obj)
	{
		buffer.in(obj);
		return buffer;
	}
	template<typename T>
	friend Buffer& operator >>(Buffer& buffer,T& obj)
	{
		buffer.out(obj);
		return buffer;
	}
protected:

private:
	__byte* b;//缓冲区
	DWORD capacity;//已经分配的内存
	DWORD size;//使用的大小
	DWORD pos;//用于读取数据的指针
	bool candelete;

};

_NAMESPACE_END